import logging
import re
import xml.etree.ElementTree as ET
import time
from xml_builder import XMLBuilder  
from utils import SIPUtils 

class CommandProcessor:
    def __init__(self, sip_client, media_streamer, device_controller):
        self.sip_client = sip_client
        self.media_streamer = media_streamer
        self.device_controller = device_controller
        self.config = sip_client.config
        self.logger = logging.getLogger('CommandProcessor')
    
    def handle_message(self, data, addr):
        try:
            message = data.decode('utf-8', errors='ignore')
        except Exception as e:
            self.logger.error(f"消息解码失败: {e}")
            return
            
        # 添加详细调试日志
        lines = message.split('\r\n')
        first_line = lines[0] if lines else ""
        
        self.logger.info(f"收到消息来自 {addr}, 大小: {len(data)}字节")
        self.logger.info(f"第一行: {first_line}")
        self.logger.info(f"消息前200字符:\n{message[:200]}...")
        
        # 记录原始十六进制数据用于调试
        self.logger.debug(f"原始数据(hex): {data[:100].hex()}")
        
        # 更精确的消息类型识别
        if message.startswith("INVITE "):
            self.logger.info("=== 识别为INVITE请求 ===")
            self.logger.info(f"完整INVITE消息:\n{message}")
            self._handle_invite(data, addr)
        elif message.startswith("ACK "):
            self.logger.info("=== 识别为ACK请求 ===")
            self._handle_ack(message)
        elif message.startswith("MESSAGE "):
            self.logger.info("=== 识别为MESSAGE请求 ===")
            self._handle_sip_message(message, addr)
        elif message.startswith("SUBSCRIBE "):
            self.logger.info("=== 识别为SUBSCRIBE请求 ===")
            self._handle_subscribe(message, addr)
        elif message.startswith("BYE "):
            self.logger.info("=== 识别为BYE请求 ===")
            self._handle_bye(message, addr)
        elif message.startswith("SIP/2.0"):
            self.logger.info(f"=== 收到SIP响应 ===: {first_line}")
            # 这是响应消息，不是请求，通常不需要处理
        else:
            self.logger.info(f"未知消息类型，内容: {message[:100]}...")
            # 记录更多调试信息
            self.logger.warning(f"完整未知消息:\n{message}")
            self.logger.debug(f"消息头部(前10行):")
            for i, line in enumerate(lines[:10]):
                self.logger.debug(f"  {i+1}: {line}")
                
            # 检查是否包含关键字但位置不对
            if "INVITE" in message:
                self.logger.warning("消息包含INVITE但不在开头！")
                # 查找INVITE在消息中的位置
                invite_pos = message.find("INVITE")
                self.logger.warning(f"INVITE出现在位置: {invite_pos}")
                self.logger.warning(f"INVITE前的内容: {repr(message[:invite_pos])}")
            if "MESSAGE" in message:
                self.logger.warning("消息包含MESSAGE但不在开头！")
    
    def _handle_sip_message(self, message, addr):
        headers = SIPUtils.parse_sip_headers(message)
        
        # 添加调试日志
        self.logger.info(f"收到SIP消息来自 {addr}")
        self.logger.debug(f"消息内容: {message[:200]}...")
        
        # 先回复200 OK
        self.sip_client.send_response(
            addr, 
            "200 OK", 
            headers
        )
        
        # 解析XML内容
        if "<?xml" in message or "<Query>" in message:
            xml_start = message.find('<?xml')
            if xml_start == -1:
                xml_start = message.find('<Query>')
            xml_content = message[xml_start:]
            
            if "Catalog" in xml_content:
                self.logger.info("处理目录查询")
                self._handle_catalog_query(message, addr)
            elif "DeviceInfo" in xml_content:
                self.logger.info("处理设备信息查询")
                self._handle_device_info_query(message, addr)
            elif "DeviceStatus" in xml_content:
                self.logger.info("处理设备状态查询")
                self._handle_device_status_query(message, addr)
            elif "RecordInfo" in xml_content:
                self.logger.info("处理录像信息查询")
                self._handle_record_query(message, addr)
            elif "DeviceControl" in xml_content:
                self.logger.info("处理设备控制")
                self._handle_device_control(message, addr)
            elif "Broadcast" in xml_content:
                self.logger.info("处理广播")
                self._handle_broadcast(message, addr)
            elif "Alarm" in xml_content:
                self.logger.info("处理报警")
                self._handle_alarm(message, addr)
            else:
                self.logger.info(f"未知消息类型，内容: {message[:100]}...")
    
    def _handle_invite(self, data, addr):
        message = data.decode()
        headers = SIPUtils.parse_sip_headers(message)
        
        self.logger.info(f"处理INVITE请求来自 {addr}")
        self.logger.info("=== 完整INVITE消息 ===")
        self.logger.info(message)
        self.logger.info("=== INVITE消息结束 ===")
        
        # 解析WVP发送的SDP以获取媒体信息
        remote_media_ip = addr[0]  # 默认使用WVP的IP
        remote_media_port = 9000   # 默认端口
        ssrc = None  # SSRC值
        
        # 从INVITE中的SDP提取媒体端口
        sdp_start = message.find('\r\n\r\n')
        if sdp_start != -1:
            sdp_content = message[sdp_start + 4:]
            self.logger.info(f"提取到SDP内容:\n{sdp_content}")
            
            try:
                # 解析SDP内容
                lines = sdp_content.split('\r\n')
                for line in lines:
                    if line.startswith('c=IN IP4'):
                        # 提取媒体IP地址
                        parts = line.split()
                        if len(parts) >= 3:
                            remote_media_ip = parts[2]
                            self.logger.info(f"从SDP提取到媒体IP: {remote_media_ip}")
                    elif line.startswith('m=video'):
                        # 提取视频端口
                        parts = line.split()
                        if len(parts) >= 2:
                            remote_media_port = int(parts[1])
                            self.logger.info(f"从SDP提取到媒体端口: {remote_media_port}")
                    elif line.startswith('y='):
                        # 提取SSRC值 (GB28181标准)
                        ssrc_str = line[2:].strip()
                        if ssrc_str:
                            ssrc = int(ssrc_str)
                            self.logger.info(f"从SDP提取到SSRC: {ssrc} (0x{ssrc:08x})")
            except Exception as e:
                self.logger.warning(f"解析SDP失败: {e}")
        else:
            self.logger.warning("INVITE消息中未找到SDP内容")
        
        self.logger.info(f"最终媒体目标: {remote_media_ip}:{remote_media_port}, SSRC: {ssrc}")
        
        # 构建SDP响应，使用正确的本地媒体端口
        sdp_response = self._build_sdp()
        
        # 立即发送200 OK响应，不等待ACK
        self.sip_client.send_response(
            addr, 
            "200 OK", 
            headers, 
            sdp_response,
            content_type="application/sdp"
        )
        
        self.logger.info("立即发送200 OK响应带SDP")
        
        # 立即启动媒体流，无需等待ACK (快速响应优化)
        self.logger.info(f"立即启动媒体流到: {remote_media_ip}:{remote_media_port}, SSRC: {ssrc}")
        self.media_streamer.start_stream(
            remote_media_ip, 
            remote_media_port, 
            ssrc
        )
        
        # 保存媒体参数供ACK确认使用
        self.pending_media_params = {
            'ip': remote_media_ip,
            'port': remote_media_port,
            'ssrc': ssrc,
            'call_id': headers.get('Call-ID', '')
        }
        
        # 重置ACK事件，准备接收新的ACK
        self.sip_client.ack_event.clear()
        
        # 在单独线程中等待ACK（仅用于日志记录）
        import threading
        ack_thread = threading.Thread(target=self._wait_for_ack_async, daemon=True)
        ack_thread.start()
    
    def _wait_for_ack_async(self):
        # 等待ACK确认（仅用于日志记录，媒体流已提前启动）
        if self.sip_client.wait_for_ack(timeout=5):
            self.logger.info("收到ACK确认，点播流程完成")
        else:
            self.logger.warning("等待ACK超时(5秒)，但媒体流已正常运行")
    
    def _handle_ack(self, message):
        self.logger.info("收到ACK确认")
        self.sip_client.ack_received()
    
    def _handle_catalog_query(self, message, addr):
        self.logger.info("处理目录查询")
        headers = self._parse_headers(message)
        
        # 先回复200 OK
        self.sip_client.send_response(
            addr, 
            "200 OK", 
            headers
        )
        
        # 解析XML内容
        try:
            xml_start = message.find('<?xml')
            if xml_start == -1:
                xml_start = message.find('<Query>')
            if xml_start == -1:
                self.logger.error("目录查询中未找到XML")
                return
            
            xml_content = message[xml_start:]
            root = ET.fromstring(xml_content)
            
            # 解析SN
            sn_element = root.find('SN')
            sn = sn_element.text if sn_element is not None else str(int(time.time()))
            
            # 使用配置信息创建目录响应
            catalog_xml = XMLBuilder.catalog_response(
                self.config.device_id,
                self.config.channel_id,
                self.config.local_ip,
                sn
            )
            
            self.sip_client.send_message(
                catalog_xml,
                content_type="Application/MANSCDP+xml"
            )
            
        except Exception as e:
            self.logger.error(f"目录查询错误: {e}")
    
    def _handle_device_info_query(self, message, addr):
        headers = self._parse_headers(message)
        
        # 先回复200 OK
        self.sip_client.send_response(
            addr, 
            "200 OK", 
            headers
        )
        
        # 发送DeviceInfo响应
        device_info_xml = XMLBuilder.device_info_response(
            self.config.device_id,
            self.config.device_info
        )
        
        self.sip_client.send_message(
            device_info_xml,
            content_type="Application/MANSCDP+xml"
        )
    
    def _handle_record_query(self, message, addr):
        headers = self._parse_headers(message)
        
        # 先回复200 OK
        self.sip_client.send_response(
            addr, 
            "200 OK", 
            headers
        )
        
        # 解析录像查询参数
        try:
            xml_start = message.find('<?xml')
            if xml_start == -1:
                xml_start = message.find('<Query>')
            if xml_start == -1:
                self.logger.error("录像查询中未找到XML")
                return
            
            xml_content = message[xml_start:]
            root = ET.fromstring(xml_content)
            
            device_id = root.find('DeviceID').text
            channel_id = root.find('ChannelID').text
            start_time = root.find('StartTime').text
            end_time = root.find('EndTime').text
            
            # 使用设备控制器查询录像
            records = self.device_controller.query_recordings(
                channel_id, 
                start_time,
                end_time
            )
            
            # 发送录像响应
            record_xml = XMLBuilder.playback_response(
                device_id,
                records
            )
            
            self.sip_client.send_message(
                record_xml,
                content_type="Application/MANSCDP+xml"
            )
            
        except Exception as e:
            self.logger.error(f"录像查询处理失败: {str(e)}")
    
    def _handle_device_control(self, message, addr):
        headers = self._parse_headers(message)
        
        # 先回复200 OK
        self.sip_client.send_response(
            addr, 
            "200 OK", 
            headers
        )
        
        # 解析控制命令
        try:
            xml_start = message.find('<?xml')
            if xml_start == -1:
                xml_start = message.find('<Control>')
            if xml_start == -1:
                self.logger.error("设备控制中未找到XML")
                return
            
            xml_content = message[xml_start:]
            root = ET.fromstring(xml_content)
            
            device_id = root.find('DeviceID').text
            command = root.find('PTZCmd').text
            
            # 使用设备控制器执行PTZ命令
            self.device_controller.execute_ptz_command(
                device_id, 
                command
            )
            
            # 发送控制响应
            control_xml = XMLBuilder.ptz_response(
                device_id,
                "OK"
            )
            
            self.sip_client.send_message(
                control_xml,
                content_type="Application/MANSCDP+xml"
            )
            
        except Exception as e:
            self.logger.error(f"设备控制处理失败: {str(e)}")
    
    def _handle_broadcast(self, message, addr):
        # 语音广播处理
        # 这里暂时忽略，设备作为客户端通常不需要处理广播
        pass
    
    def _handle_alarm(self, message, addr):
        # 报警处理
        # 这里暂时忽略，设备作为客户端通常不需要处理报警
        pass
    
    def _handle_subscribe(self, message, addr):
        """处理SUBSCRIBE请求（目录订阅）"""
        headers = SIPUtils.parse_sip_headers(message)
        
        self.logger.info(f"收到SUBSCRIBE来自 {addr}")
        self.logger.debug(f"SUBSCRIBE内容: {message[:200]}...")
        
        # 发送200 OK响应
        self.sip_client.send_response(
            addr, 
            "200 OK", 
            headers
        )
        
        # 目录订阅总是需要发送Catalog通知
        # 生成一个新的SN用于SUBSCRIBE响应
        sn = str(int(time.time()))
        self.logger.info(f"发送目录订阅通知 SN: {sn}")
        
        catalog_xml = XMLBuilder.catalog_response(
            self.config.device_id,
            self.config.channel_id,
            self.config.local_ip,
            sn
        )
        
        self.sip_client.send_message(
            catalog_xml,
            content_type="Application/MANSCDP+xml"
        )
    
        self.logger.info("SUBSCRIBE处理成功")
    
    def _handle_bye(self, message, addr):
        """处理BYE请求"""
        headers = SIPUtils.parse_sip_headers(message)
        
        self.logger.info(f"收到BYE来自 {addr}")
        
        # 发送200 OK响应
        self.sip_client.send_response(
            addr, 
            "200 OK", 
            headers
        )
        
        # 停止媒体流
        self.media_streamer.stop_stream()
        
        self.logger.info("BYE处理完成，媒体流已停止")
    
    def _handle_device_status_query(self, message, addr):
        """处理设备状态查询"""
        headers = self._parse_headers(message)
        
        # 先回复200 OK
        self.sip_client.send_response(
            addr, 
            "200 OK", 
            headers
        )
        
        # 发送设备状态响应
        status_xml = XMLBuilder.device_status_response(
            self.config.device_id
        )
        
        self.sip_client.send_message(
            status_xml,
            content_type="Application/MANSCDP+xml"
        )
    
    def _build_sdp(self):
        """构建SDP响应 - H.264 RTP格式"""
        # 使用动态端口而不是硬编码的9000
        local_media_port = getattr(self.config, 'local_media_port', 9000)
        
        # 使用标准H.264 RTP格式，更好的兼容性
        sdp = f"""v=0
o={self.config.device_id} 0 0 IN IP4 {self.config.local_ip}
s=GB28181
c=IN IP4 {self.config.local_ip}
t=0 0
m=video {local_media_port} RTP/AVP 98
a=rtpmap:98 H264/90000
a=recvonly
"""
        
        self.logger.info(f"构建SDP响应，本地媒体端口: {local_media_port}")
        return sdp
    
    def _parse_headers(self, message):
        """解析SIP头部"""
        headers = {}
        lines = message.split('\r\n')
        for line in lines:
            if ':' in line:
                key, value = line.split(':', 1)
                headers[key.strip()] = value.strip()
        return headers